package com.tianji.learning.service.impl;

import ch.qos.logback.classic.spi.EventArgUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.course.SectionInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author ffk
 * @since 2024-06-20
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {


    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final LearningLessonMapper learningLessonMapper;
    private final LearningRecordMapper learningRecordMapper;

    /**
     * 添加课程
     */
    @Override
    public void addLessons(Long userId, List<Long> courseIds) {//添加的用户id，课程id列表
        //根据课程id查询课程信息
        List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(courseIds);
        if(ObjectUtils.isEmpty(courseInfoList)){
           log.error("课程信息为空");
           return;
        }

        Map<Long, Integer> validDurationMap = courseInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, CourseSimpleInfoDTO::getValidDuration));

        List<LearningLesson> lessonList = new ArrayList<>();

        for (CourseSimpleInfoDTO courseSimpleInfoDTO : courseInfoList) {
            LearningLesson lesson = new LearningLesson();
            lesson.setUserId(userId);
            lesson.setCourseId(courseSimpleInfoDTO.getId());

            Long id = courseSimpleInfoDTO.getId();//课程id
            Integer validDuration = validDurationMap.get(id);//有效时间

            if(validDuration>0 && validDuration!=9999){
                lesson.setExpireTime(LocalDateTime.now().plusMonths(validDuration));
            }

            if(validDuration>0 && validDuration==9999){
                lesson.setExpireTime(LocalDateTime.now().plusMonths(9999));
            }

            lessonList.add(lesson);
        }
        saveBatch(lessonList);
    }

    /**
     * 分页查询
     */
    @Override
    public PageDTO<LearningLessonVO> queryByPage(PageQuery pageQuery) {
        Long userId = UserContext.getUser();


        //Page对象大致包含以下重要属性和方法：
        //total: 总记录数，即满足条件的所有记录数量，不分页情况下的总数。
        //pages: 总页数，根据每页大小和总记录数计算得出。
        //size: 每页显示的记录数，即分页查询时请求的每页大小。
        //current: 当前页码。
        //records: 当前页的数据列表，类型为List<LearningLesson>，包含了当前页的所有LearningLesson实体对象。
        Page<LearningLesson> page = lambdaQuery().eq(LearningLesson::getUserId, userId)
                .page(pageQuery.toMpPage("latest_learn_time", false));

        //当前页数据列表
        List<LearningLesson> records = page.getRecords();
        if(ObjectUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }


        //去获取课程的几个信息哈哈
        Set<Long> courseId = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());
        List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(courseId);
        if(ObjectUtils.isEmpty(courseInfoList)){
            throw new BadRequestException("课程信息为空");
        }

        Map<Long, CourseSimpleInfoDTO> courseMap = courseInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));

        //返回的数据集合
        List<LearningLessonVO> pageList=new ArrayList<>(records.size());
        //po转vo同时把课程赋值
        for (LearningLesson lesson : records) {
            LearningLessonVO learningLessonVO = BeanUtils.copyBean(lesson, LearningLessonVO.class);
            CourseSimpleInfoDTO courseInfo = courseMap.get(lesson.getCourseId());

            learningLessonVO.setCourseName(courseInfo.getName());
            learningLessonVO.setCourseCoverUrl(courseInfo.getCoverUrl());
            learningLessonVO.setSections(courseInfo.getSectionNum());//小节数量

            pageList.add(learningLessonVO);
        }

        return PageDTO.of(page,pageList);
    }


    /**
     * 查询最近当前正在学习的课程
     */
    @Override
    public LearningLessonVO queryNowLesson() {
        Long userId = UserContext.getUser();

        LearningLesson nowLesson = lambdaQuery().eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .last("limit 1")
                .one();

        if(ObjectUtils.isEmpty(nowLesson)){
            log.info("用户没有学习任何课程");
            return null;
        }

        log.info("用户的最近学习课程信息为{}", nowLesson);

         LearningLessonVO learningLessonInfo = BeanUtils.toBean(nowLesson, LearningLessonVO.class);

         //赋值课程信息
         CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(nowLesson.getCourseId(), false, false);
            if(ObjectUtils.isEmpty(courseInfo)){
                throw new BadRequestException("课程没有啊喂");
            }

         learningLessonInfo.setCourseName(courseInfo.getName());
         learningLessonInfo.setCourseCoverUrl(courseInfo.getCoverUrl());
         learningLessonInfo.setSections(courseInfo.getSectionNum());

         //课程总数
         Integer count = lambdaQuery().eq(LearningLesson::getUserId, userId).count();
         learningLessonInfo.setCourseAmount(count);

         //根据章节查小节信息
        List<CataSimpleInfoDTO> cataLogueSimpleInfoList = catalogueClient.batchQueryCatalogue(List.of(nowLesson.getLatestSectionId()));
        if(ObjectUtils.isNotEmpty(cataLogueSimpleInfoList)){
            CataSimpleInfoDTO cataSimpleInfo = cataLogueSimpleInfoList.get(0);
            learningLessonInfo.setLatestSectionName(cataSimpleInfo.getName());
            learningLessonInfo.setLatestSectionIndex(cataSimpleInfo.getCIndex());
        }
        return learningLessonInfo;
    }

    /**
     * 查询课程是否在有效期
     */
    @Override
    public Long isLessonValid(Long courseId) {

         Long userId = UserContext.getUser();
         log.info("查询用户的课表里是否有这个课程，此时的用户id是：{}", userId);
         if(ObjectUtils.isEmpty(userId)){
             return null;
         }
         LearningLesson learningLessonMsg = lambdaQuery().eq(LearningLesson::getCourseId, courseId)
                .eq(LearningLesson::getUserId, userId)
                 .one();
         if(ObjectUtils.isEmpty(learningLessonMsg)){
             log.info("用户课表中没有该课程，不能观看啊喂");
             return null;
         }

         if(learningLessonMsg.getStatus()== LessonStatus.EXPIRED){
             log.info("课程已经失效了，不能观看咯");
             return null;
         }

         log.info("课程还真有效，看视频咯");
        return learningLessonMsg.getId();
    }

    /**
     * 查询课程 学习人数
     */
    @Override
    public Integer countLearningLessonByCourse(Long courseId) {
        return lambdaQuery().eq(LearningLesson::getCourseId, courseId).count();
    }

    /**
     * 查询课程
     */
    @Override
    public LearningLessonVO queryLesson(Long courseId) {
         Long userId = UserContext.getUser();
         LearningLesson one = lambdaQuery().eq(LearningLesson::getCourseId, courseId)
                .eq(LearningLesson::getUserId, userId)
                .one();

        if(ObjectUtils.isNotEmpty(one)){
            return BeanUtils.copyBean(one, LearningLessonVO.class);
         }
        return null;
    }

    @Override
    public void deleteByUserAndCourseId(Long userId, List<Long> courseIds) {
         int asw = learningLessonMapper.delete(
                new QueryWrapper<LearningLesson>()
                        .eq("user_id", userId)
                        .in("course_id", courseIds)
        );

         log.info("进行了删除，影响的行数：{}",asw);
    }

    /**
     * 分页查询学习计划
     * @param pageQuery
     * @return
     */
    @Override
    public LearningPlanPageVO queryPlanPage(PageQuery pageQuery) {
        LearningPlanPageVO pageVo=new LearningPlanPageVO();
        Long userId = UserContext.getUser();

        //分页查询该用户
         Page<LearningLesson> lessonInfo = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                 .eq(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING)
                 .in(LearningLesson::getStatus, LessonStatus.NOT_BEGIN,LessonStatus.LEARNING)
                .page(pageQuery.toMpPage("latest_learn_time", false));
        //分页数据
        List<LearningLesson> records = lessonInfo.getRecords();
         if(ObjectUtils.isEmpty(records)){
             log.info("搞什么，怎么没有课程信息");
             return pageVo.pageInfo(lessonInfo.getTotal(),lessonInfo.getPages(),CollUtils.emptyList());
         }

        //获取本周的开始和结束时间
        LocalDateTime start = DateUtils.getDayStartTime(LocalDateTime.now());
        LocalDateTime end = DateUtils.getDayEndTime(LocalDateTime.now());


        //看完的总小节总数，不分科目
         LambdaQueryWrapper<LearningRecord> wrapper = new LambdaQueryWrapper<LearningRecord>()
                .eq(LearningRecord::getUserId, userId)
                .eq(LearningRecord::getFinished, true)
                .between(LearningRecord::getFinishTime, start, end);
         Integer sectionCount = learningRecordMapper.selectCount(wrapper);
         pageVo.setWeekFinished(sectionCount);

         //计划的总小节数目，每周都是这些计划，没有结束的话
        // select sum(week_freq) from learning_record where userId=#{userId}
         LearningLesson sumFreq = query().select("sum(week_freq) as total_frep")
                .eq("user_d", userId)
                 .eq("plan_status", PlanStatus.PLAN_RUNNING)
                .in("status", LessonStatus.NOT_BEGIN, LessonStatus.LEARNING)
                .one();
        pageVo.setWeekTotalPlan(sumFreq.getTotal_frep());

        //简单课程信息接口可传ids
         Set<Long> courseIds = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());
         List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(courseIds);
            if(ObjectUtils.isEmpty(courseInfoList)){
                throw new BadRequestException("根据ids远程调用course,查到的课程信息为空");
            }
            Map<Long, CourseSimpleInfoDTO> courseMap = courseInfoList.stream().collect(Collectors.toMap(c->c.getId(),c->c));

            //分组查到每门课程在本周已经看过的小节数
         QueryWrapper<LearningRecord> recordQueryWrapper = new QueryWrapper<>();
         recordQueryWrapper.select("lesson_id as id,count(*) as weekSee")
                            .eq("user_id", userId)
                            .eq("finished",true)
                            .between("finish_time",start,end)
                            .groupBy("lesson_id");
        //每个map是每一行的数据，其中键是列名称，即lessonid，值是每一列的数据
         List<Map<String, Object>> mapList = learningRecordMapper.selectMaps(recordQueryWrapper);
         Map<Long, Long> sectionWeekSee = mapList.stream().collect(Collectors.toMap(c -> Long.parseLong(c.get("id").toString()), c -> Long.parseLong(c.get("weekSee").toString())));

        //封装list
        List<LearningPlanVO> lessonPlanList=new ArrayList<>();
        for (LearningLesson record : records) {
             LearningPlanVO learningPlanVO = BeanUtils.copyBean(record, LearningPlanVO.class);
             learningPlanVO.setCourseName(courseMap.get(record.getCourseId()).getName());
             learningPlanVO.setSections(courseMap.get(record.getCourseId()).getSectionNum());//小节数量
            learningPlanVO.setWeekLearnedSections(sectionWeekSee.getOrDefault(record.getId(),0L).intValue());

            lessonPlanList.add(learningPlanVO);
        }

        //pageVo.setList(lessonPlanList);
        pageVo.setWeekPoints(666);

        return pageVo.pageInfo(lessonInfo.getTotal(),lessonInfo.getPages(),lessonPlanList);
    }


}
